#pragma once
#include "Util.hpp"
#include <assert.h>
#include<mutex>

// 数据库管理模块

class user_table
{
public:
    user_table(const std::string& host ,const std::string& username,
    const std::string& pwd,const std::string& dbname,const uint16_t port)
    {
        _mysql = UtilMysql::mysql_create(host,username,pwd,dbname,port);
        assert(_mysql != NULL);
    }
    ~user_table()
    {
        UtilMysql::mysql_destroy(_mysql);
        _mysql = NULL;
    }
    // 用户注册
    bool insert(Json::Value &user)
    {
        // 插入sql语句
#define INSERT_USER "insert user values(null,'%s',password('%s'),1000,0,0);"
        char sql[4096] = {0};
        sprintf(sql, INSERT_USER, user["username"].asCString(), user["password"].asCString());

        // 查询一下用户名是否存在
        Json::Value val;
        bool ret = select_by_name(user["username"].asString(), val);
        if (ret)
        {
            // 用户名已存在
            DLOG("%s is already exists", user["username"].asCString());
            return false;
        }

        // 执行sql语句
        ret = UtilMysql::mysql_exec(_mysql, sql);
        if (!ret)
        {
            DLOG("insert user info failed!");
            return false;
        }
        return true;
    }
    bool login(Json::Value &user)
    {
#define LOGIN_USER "select id,score,total_count,win_count from user where username='%s' and password=password('%s');"
        char sql[4096] = {0};
        sprintf(sql, LOGIN_USER, user["username"].asCString(), user["password"].asCString());
        MYSQL_RES *res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex); //锁的管理器
            // 执行sql语句
            bool ret = UtilMysql::mysql_exec(_mysql, sql);
            if (!ret)
            {
                DLOG("\"%s\" Execution error", sql);
                return false;
            }

            // 获取查询结果集
            res = mysql_store_result(_mysql);
            if (ret == NULL) // 结果集为空，没有查找到
            {
                DLOG("there are no user information!");
                return false;
            }
        }
        int row_num = mysql_num_rows(res); // 获取结果的行数
        if (row_num != 1)
        {
            // 只能查询到一条用户,不是一个用户就报错
            DLOG("this user information is not unique");
            mysql_free_result(res);
            return false;
        }
        // 获取该行数据
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = std::stoi(row[0]);
        user["score"] = std::stoi(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);

        std::cout << " login success " << std::endl;
        std::cout << "用户名 : " << user["username"].asString() << std::endl; 
        std::cout << "ID : " << user["id"].asInt() << std::endl; 
        std::cout << "分数 : " << user["score"].asInt() << std::endl; 
        std::cout << "总场数 : " << user["total_count"].asInt() << std::endl; 
        std::cout << "胜场数 : " << user["win_count"].asString() << std::endl; 
    
        mysql_free_result(res);
        return true;
    }
    // 通过用户名查找用户信息
    bool select_by_name(const std::string &name, Json::Value &user)
    {
#define SELECT_BY_NAME "select id,score,total_count,win_count from user where username='%s';"
        char sql[4096] = {0};
        sprintf(sql, SELECT_BY_NAME, name.c_str());
        
        //临界资源区域
         MYSQL_RES *res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex); //锁的管理器
            // 执行sql语句
            bool ret = UtilMysql::mysql_exec(_mysql, sql);
            if (!ret)
            {
                DLOG("\"%s\" Execution error", sql);
                return false;
            }

            // 获取查询结果集
            res = mysql_store_result(_mysql);
            if (ret == NULL) // 结果集为空，没有查找到
            {
                DLOG("there are no user information!");
                return false;
            }
        }

        int row_num = mysql_num_rows(res); // 获取结果的行数
        if (row_num != 1)
        {
            // 只能查询到一条用户,不是一个用户就报错
            DLOG("this user information is not unique");
            mysql_free_result(res);
            return false;
        }
        // 获取该行数据
        MYSQL_ROW row = mysql_fetch_row(res);
        user["username"] = name;
        user["id"] = std::stoi(row[0]);
        user["score"] = std::stoi(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);

        mysql_free_result(res);
        return true;
    }
    // 通过id查找用户信息
    bool select_by_id(int id, Json::Value &user)
    {
#define SELECT_BY_ID "select username,score,total_count,win_count from user where id=%d;"
        char sql[4096] = {0};
        sprintf(sql, SELECT_BY_ID, id);

        //临界资源区域
         MYSQL_RES *res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex); //锁的管理器
            // 执行sql语句
            bool ret = UtilMysql::mysql_exec(_mysql, sql);
            if (!ret)
            {
                DLOG("\"%s\" Execution error", sql);
                return false;
            }

            // 获取查询结果集
            res = mysql_store_result(_mysql);
            if (ret == NULL) // 结果集为空，没有查找到
            {
                DLOG("there are no user information!");
                return false;
            }
        }

        int row_num = mysql_num_rows(res); // 获取结果的行数
        if (row_num != 1)
        {
            // 只能查询到一条用户,不是一个用户就报错
            DLOG("this user information is not unique");
            mysql_free_result(res);
            return false;
        }
        // 获取该行数据
        MYSQL_ROW row = mysql_fetch_row(res);
        user["username"] = row[0];
        user["id"] = id;
        user["score"] = std::stoi(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);

        mysql_free_result(res);
        return true;
    }
    bool win(int id)
    {
#define USER_WIN "update user set score=score+30,total_count=total_count+1,win_count=win_count+1 where id=%d;"
        char sql[4096] = {0};
        sprintf(sql, USER_WIN, id);
        // 执行sql语句
        bool ret = UtilMysql::mysql_exec(_mysql, sql);
        if (!ret)
        {
            DLOG("\"%s\" Execution error", sql);
            return false;
        }
        return true;
    }
    bool lose(int id)
    {
#define USER_LOSE "update user set score=score-30,total_count=total_count+1 where id=%d;"
        char sql[4096] = {0};
        sprintf(sql, USER_LOSE, id);
        // 执行sql语句
        bool ret = UtilMysql::mysql_exec(_mysql, sql);
        if (!ret)
        {
            DLOG("\"%s\" Execution error", sql);
            return false;
        }
        return true;
    }

private:
    MYSQL *_mysql;
    std::mutex _mutex;
};
